﻿using System;
using System.Collections.Generic;

namespace Glue.Internals
{
    internal class NestedObjectCreator : INestedObjectCreator
    {
        private readonly CreatorContainer container;

        public NestedObjectCreator(CreatorContainer container)
        {
            this.container = container;
        }

        public bool TryCreateAllObjectsInPath(object theObject, IEnumerable<IObjectMemberAccessor> memberAccessors)
        {
            var tempObject = theObject;
            if (!Validate(memberAccessors)) return false;
            foreach (var accessor in memberAccessors)
            {
                var maybeExistingObject = accessor.InvokeGet(tempObject);
                if (maybeExistingObject.HasValue())
                {
                    tempObject = maybeExistingObject.GetValue();
                }
                else
                {
                    var newObject = CreateObject(accessor.PropertyType);
                    accessor.InvokeSet(tempObject, newObject);
                    tempObject = newObject;
                }
            }
            return true;
        }

        private bool Validate(IEnumerable<IObjectMemberAccessor> memberAccessors)
        {
            foreach (var accessor in memberAccessors)
            {
                if (!accessor.CanSetValues || !accessor.CanGetValues || !container.Contains(accessor.PropertyType   )) return false;
            }
            return true;
        }

        private object CreateObject(Type type)
        {
            return container.Get(type)(null);
        }
    }
}
